package com.ccp.dev.qbdms.expimp.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ccp.dev.core.util.BeanUtils;
import com.ccp.dev.core.util.StringUtil;
import com.ccp.dev.qbdms.expimp.annotation.ExpAnnotation;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 导入导出辅助类
 */
public class AuxiliaryUtil {
    /**
     * 解析model 用于展现列
     * @param cls  类
     * @return  jsonObject
     * @throws Exception throw E
     */
    public static JSONObject resolverModel(Class<?> cls) throws Exception{
        if(BeanUtils.isEmpty(cls)){
            throw new IllegalArgumentException("参数不能为空！");
        }
        if(cls.isPrimitive()){
            throw new IllegalArgumentException("参数不能为基本类型!");
        }
        return resolverSubModel(cls,new JSONObject(),0);
    }
    /**
     * 解析model 用于展现列,用于区分一表导出不同字段操作
     * @param cls  类
     * @param level 字段分组标记
     * @return  jsonObject
     * @throws Exception throw E
     */
    public static JSONObject resolverModel(Class<?> cls,int level) throws Exception{
        if(BeanUtils.isEmpty(cls)){
            throw new IllegalArgumentException("参数不能为空！");
        }
        if(cls.isPrimitive()){
            throw new IllegalArgumentException("参数不能为基本类型!");
        }
        return resolverSubModel(cls,new JSONObject(),level);
    }

    /**
     * 解析model 用于展现列
     * @param cls class
     * @param jsonObject jsonObject
     * @param level 字段分组标记
     * @return jsonObject
     */
    private static JSONObject resolverSubModel(Class<?> cls,JSONObject jsonObject,int level){
        ExpAnnotation expAnnotation = cls.getAnnotation(ExpAnnotation.class);
        Field[] fields = null;
        fields = getAllField(cls);
        JSONArray subTableArr = new JSONArray();
        JSONArray fieldJsonArr = new JSONArray();
        for (Field field : fields) {
            ExpAnnotation filedAnnotation = field.getAnnotation(ExpAnnotation.class);
            //获取字段类型
            Class<?> subClass =  field.getType();
            if(BeanUtils.isNotEmpty(filedAnnotation) && filedAnnotation.level() <= level){
                if(filedAnnotation.isSubTable()){
                    //如果是子表并且不是基本类型
                    if(subClass.isArray()){
                        subClass = subClass.getComponentType();
                    }else if(Collection.class.isAssignableFrom(subClass)){
                        Type type = field.getGenericType();
                        if (null == type) {
                            continue;
                        }
                        if (type instanceof ParameterizedType) {
                            ParameterizedType pt = (ParameterizedType) type;
                            subClass = (Class<?>)pt.getActualTypeArguments()[0];
                        }
                    }
                    if(null != subClass){
                        JSONObject currObj = resolverSubModel(subClass,new JSONObject(),level);
                        currObj.put("tableModelName",field.getName());
                        subTableArr.add(currObj);
                    }
                }else{
                    JSONObject jo = new JSONObject();
                    jo.put("key",field.getName());
                    jo.put("value", StringUtil.isEmpty(filedAnnotation.description())?field.getName():filedAnnotation.description());
                    fieldJsonArr.add(jo);
                }
            }
        }
        jsonObject.put("tableName",BeanUtils.isEmpty(expAnnotation)?cls.getSimpleName():StringUtil.isEmpty(expAnnotation.description())?cls.getSimpleName():expAnnotation.description());
        jsonObject.put("tableModelName",cls.getSimpleName());
        jsonObject.put("subTable",subTableArr);
        jsonObject.put("fields",fieldJsonArr);
        return jsonObject;
    }

    /**
     * 反射获取所有字段
     * @param c 原始类
     * @return 字段数组
     */
    public static Field[] getAllField(Class c){
        List<Field> fields = new ArrayList<>();
        Class tempClass = c;
        while (tempClass != null) {
            fields.addAll(Arrays.asList(tempClass .getDeclaredFields()));
            tempClass = tempClass.getSuperclass();
        }
        return fields.toArray(new Field[]{});
    }

    /**
     * 反射获取所有字段
     * @param c 原始类
     * @return 字段数组
     */
    public static Field getFieldByName(Class c , String name){
        Field[] fields = getAllField(c);
        List<Field> list = Arrays.asList(fields);
        list = list.stream().filter(a->a.getName().equals(name)).collect(Collectors.toList());
        return list.get(0);
    }
}
